package com.sian.datasource;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;

/**
 *@See PreparedStatement  
 *@author desert
 *@version 1.0
 */
public class C1PreparedStatement extends C1Statement implements PreparedStatement{
   
	 public final static int P6_MAX_FIELDS = 32;
	    public static int P6_GROW_MAX = 32;
	    protected PreparedStatement prepStmtPassthru;
	    protected String preparedQuery;
	    protected Object values[];
	    protected boolean isString[];
	    
	    public C1PreparedStatement(C1Factory factory, PreparedStatement statement, C1Connection conn, String query) {
	        super(factory, statement, conn);
	        prepStmtPassthru = statement;
	        this.preparedQuery = query;
	        initValues();
	    }
	    
	    protected void initValues() {
	        values = new Object[P6_MAX_FIELDS+1];
	        isString = new boolean[P6_MAX_FIELDS+1];
	    }
	    
	    public void addBatch() throws SQLException {
	    	C1WriteLog.WriteLog(this.getClass().toString(), getQueryFromPreparedStatement());
	        prepStmtPassthru.addBatch();
	    }
	    
	    public void clearParameters() throws SQLException {
	        prepStmtPassthru.clearParameters();
	    }
	    
	    public boolean execute() throws SQLException {
	    	C1WriteLog.WriteLog(this.getClass().toString(), getQueryFromPreparedStatement());
	        return prepStmtPassthru.execute();
	    }
	    
	    public ResultSet executeQuery() throws SQLException {
	    	C1WriteLog.WriteLog(this.getClass().toString(), getQueryFromPreparedStatement());
	        ResultSet resultSet = prepStmtPassthru.executeQuery();
	        return (factory.getResultSet(resultSet, this, preparedQuery, getQueryFromPreparedStatement()));
	    }
	    
	    public int executeUpdate() throws SQLException {
	    	C1WriteLog.WriteLog(this.getClass().toString(), getQueryFromPreparedStatement());
	        return prepStmtPassthru.executeUpdate();
	    }
	    
	    public ResultSetMetaData getMetaData() throws SQLException {
	        return prepStmtPassthru.getMetaData();
	    }
	    
	    public void setArray(int p0, Array p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        // we need to make sure we get the real object in this case
	        if (p1 instanceof C1Array) {
	            prepStmtPassthru.setArray(p0,((C1Array)p1).passthru);
	        } else{
	            prepStmtPassthru.setArray(p0,p1);
	        }
	    }
	    
	    public void setAsciiStream(int p0, InputStream p1, int p2) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setAsciiStream(p0,p1,p2);
	    }
	    
	    public void setBigDecimal(int p0, BigDecimal p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setBigDecimal(p0,p1);
	    }

	    public void setBinaryStream(int p0, InputStream p1, int p2) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setBinaryStream(p0,p1,p2);
	    }
	    
	    public void setBlob(int p0, Blob p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setBlob(p0,p1);
	    }
	    
	    public void setBoolean(int p0, boolean p1) throws SQLException {
	        setObjectAsString(p0, new Boolean(p1));
	        prepStmtPassthru.setBoolean(p0,p1);
	    }
	    
	    public void setByte(int p0, byte p1) throws SQLException {
	        setObjectAsString(p0, new Byte(p1));
	        prepStmtPassthru.setByte(p0,p1);
	    }
	    
	    public void setBytes(int p0, byte[] p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setBytes(p0,p1);
	    }
	    
	    public void setCharacterStream(int p0, Reader p1, int p2) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setCharacterStream(p0,p1,p2);
	    }
	    
	    public void setClob(int p0, Clob p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setClob(p0,p1);
	    }
	    
	    public void setDate(int p0, Date p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setDate(p0,p1);
	    } 
	    
	    public void setDate(int p0, Date p1, java.util.Calendar p2) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setDate(p0,p1,p2);
	    }
	    
	    public void setDouble(int p0, double p1) throws SQLException {
	        setObjectAsInt(p0, new Double(p1));
	        prepStmtPassthru.setDouble(p0,p1);
	    }
	    
	    public void setFloat(int p0, float p1) throws SQLException {
	        setObjectAsInt(p0, new Float(p1));
	        prepStmtPassthru.setFloat(p0,p1);
	    }
	    
	    public void setInt(int p0, int p1) throws SQLException {
	        setObjectAsInt(p0, new Integer(p1));
	        prepStmtPassthru.setInt(p0,p1);
	    }
	    
	    public void setLong(int p0, long p1) throws SQLException {
	        setObjectAsInt(p0, new Long(p1));
	        prepStmtPassthru.setLong(p0,p1);
	    }
	    
	    public void setNull(int p0, int p1, String p2) throws SQLException {
	        setObjectAsString(p0, null);
	        prepStmtPassthru.setNull(p0,p1,p2);
	    }
	    
	    public void setNull(int p0, int p1) throws SQLException {
	        setObjectAsString(p0, null);
	        prepStmtPassthru.setNull(p0,p1);
	    }
	    
	    public void setObject(int p0, Object p1, int p2, int p3) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setObject(p0,p1,p2,p3);
	    }
	    
	    public void setObject(int p0, Object p1, int p2) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setObject(p0,p1,p2);
	    }
	    
	    public void setObject(int p0, Object p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setObject(p0,p1);
	    }
	    
	    public void setRef(int p0, Ref p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setRef(p0,p1);
	    }
	    
	    public void setShort(int p0, short p1) throws SQLException {
	        setObjectAsString(p0, new Short(p1));
	        prepStmtPassthru.setShort(p0,p1);
	    }
	    
	    public void setString(int p0, String p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setString(p0,p1);
	    }
	    
	    public void setTime(int p0, Time p1, java.util.Calendar p2) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setTime(p0,p1,p2);
	    }
	    
	    public void setTime(int p0, Time p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setTime(p0,p1);
	    }
	    
	    public void setTimestamp(int p0, Timestamp p1, java.util.Calendar p2) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setTimestamp(p0,p1,p2);
	    }
	    
	    public void setTimestamp(int p0, Timestamp p1) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setTimestamp(p0,p1);
	    }
	    
	    public void setUnicodeStream(int p0, InputStream p1, int p2) throws SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setUnicodeStream(p0,p1,p2);
	    }
	    
	    /* we override this because the p6statement version will not be 
	     * able to return the accurate prepared statement or query information
	     */
	    // bug 161: getResultSet() should return null if this is an update
	    // count or there are not more result sets
	    public java.sql.ResultSet getResultSet() throws java.sql.SQLException {
		ResultSet rs = passthru.getResultSet();
	        return (rs == null) ? null : factory.getResultSet(rs, this, preparedQuery, getQueryFromPreparedStatement());
	    }
	    
	    /*
	     * P6Spy specific functionality
	     */
	    public final String getQueryFromPreparedStatement() {
	        int len = preparedQuery.length();
	        StringBuffer t = new StringBuffer(len * 2);
	        
	        if (values != null) {
	            int i = 1, limit = 0, base = 0;
	            
	            while ((limit = preparedQuery.indexOf('?',limit)) != -1) {
	                if (isString[i]) {
	                    t.append(preparedQuery.substring(base,limit));
	                    t.append("'");
	                    t.append(values[i]);
	                    t.append("'");
	                } else {
	                    t.append(preparedQuery.substring(base,limit));
	                    t.append(values[i]);
	                }
	                i++;
	                limit++;
	                base = limit;
	            }
	            if (base < len) {
	                t.append(preparedQuery.substring(base));
	            }
	        }
	        
	        // C1WriteLog.WriteLog(this.getClass().toString(), t.toString());
	        // System.out.println("=================C1PreparedStatement(paramenter is unexcept)=============="+t.toString()+"===============");
	        
	        return t.toString();
	    }
	    
	    protected void growValues(int newMax) {
	        int size = values.length;
	        Object [] values_tmp = new Object[newMax + P6_GROW_MAX];
	        boolean [] isString_tmp = new boolean[newMax + P6_GROW_MAX];
	        System.arraycopy(values, 0, values_tmp,  0, size);
	        values = values_tmp;
	        System.arraycopy(isString, 0, isString_tmp, 0, size);
	        isString = isString_tmp;
	    }
	    
	    
	    protected  void setObjectAsString(int i, Object o) {
	        if (values != null) {
	            if (i >= 0) {
		             if ( i >= values.length) {
			            growValues(i);
			          }

	                   values[i] = (o == null) ? "" : o.toString();
	                   isString[i]  = true;
	            }
	        }
	    }
	    
	    protected  void setObjectAsInt(int i, Object o) {
	        if (values != null) {
	            if (i >=0) {    
	                if (i >= values.length) {
	                    growValues(i);
	                }
	                values[i] = (o == null) ? "" : o.toString();
	                isString[i]  = false;
	            } 
	        }
	    }

	    // Since JDK 1.4
	    public void setURL(int p0, java.net.URL p1) throws java.sql.SQLException {
	        setObjectAsString(p0, p1);
	        prepStmtPassthru.setURL(p0, p1);
	    }
	    
	    // Since JDK 1.4
	    public java.sql.ParameterMetaData getParameterMetaData() throws java.sql.SQLException {
	        return(prepStmtPassthru.getParameterMetaData());
	    }


	   public int getValuesLength() {
	     return values.length;
	    }

	
	public void setAsciiStream(int parameterIndex, InputStream x)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setAsciiStream(parameterIndex, x);
	}

	
	public void setAsciiStream(int parameterIndex, InputStream x, long length)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setAsciiStream(parameterIndex, x, length);
	}

	
	public void setBinaryStream(int parameterIndex, InputStream x)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setBinaryStream(parameterIndex, x);
	}

	
	public void setBinaryStream(int parameterIndex, InputStream x, long length)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setBinaryStream(parameterIndex, x, length);
	}

	
	public void setBlob(int parameterIndex, InputStream inputStream)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setBlob(parameterIndex, inputStream);	
	}

	
	public void setBlob(int parameterIndex, InputStream inputStream, long length)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setBlob(parameterIndex, inputStream, length);
	}

	
	public void setCharacterStream(int parameterIndex, Reader reader)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setCharacterStream(parameterIndex, reader);
	}

	
	public void setCharacterStream(int parameterIndex, Reader reader,
			long length) throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setCharacterStream(parameterIndex, reader, length);
	}

	
	public void setClob(int parameterIndex, Reader reader) throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setClob(parameterIndex, reader);
	}

	
	public void setClob(int parameterIndex, Reader reader, long length)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setClob(parameterIndex, reader, length);
	}

	
	public void setNCharacterStream(int parameterIndex, Reader value)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setNCharacterStream(parameterIndex, value);
	}

	
	public void setNCharacterStream(int parameterIndex, Reader value,
			long length) throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setNCharacterStream(parameterIndex, value, length);
	}

	
	public void setNClob(int parameterIndex, NClob value) throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setNClob(parameterIndex, value);
	}

	
	public void setNClob(int parameterIndex, Reader reader) throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setNClob(parameterIndex, reader);
	}

	
	public void setNClob(int parameterIndex, Reader reader, long length)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setNClob(parameterIndex, reader, length);
	}

	
	public void setNString(int parameterIndex, String value)
			throws SQLException {
		// TODO Auto-generated method stub
	    setObjectAsString(parameterIndex, value);
		prepStmtPassthru.setNString(parameterIndex, value);
	}

	
	public void setRowId(int parameterIndex, RowId x) throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setRowId(parameterIndex, x);
	}

	
	public void setSQLXML(int parameterIndex, SQLXML xmlObject)
			throws SQLException {
		// TODO Auto-generated method stub
		prepStmtPassthru.setSQLXML(parameterIndex, xmlObject);
	}
}
